package bean.managed;

import bean.session.RawMaterialEntityFacade;
import bean.session.RawMaterialPurchaseOrderEntityFacade;
import bean.session.RawMaterialPurchaseOrderReportEntityFacade;
import bean.session.RawMaterialQuotationFacade;
import bean.session.VendorProductPriceEntityFacade;
import entity.VendorEntity;

import bean.session.VendorEntityFacade;

import entity.AddressEntity;

import entity.RawMaterialPurchaseOrderEntity;
import entity.RawMaterialPurchaseOrderReportEntity;
import entity.RawMaterialQuotationEntity;

import entity.RawMaterialRequirementWeeklyEntity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import java.util.Set;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import javax.faces.context.FacesContext;

import managedbean.AbstractBacking;
import org.primefaces.event.RateEvent;

import org.primefaces.event.SelectEvent;

import type.AddressType;
import type.Month;
import type.RawMaterialPurchaseOrderStatus;

import type.RawMaterialQuotationType;

@ManagedBean(name = "rawMaterialPurchaseOrderEditController")
@SessionScoped
public class RawMaterialPurchaseOrderEditController extends AbstractBacking implements Serializable {

    //////////////////////////////////////////
    //private List<RawMaterialEntity> allRMEntityList;
    //private List<RawMaterialEntity> userRightsEntityList;
    //this quotation has the raw material ,true ,otherwise false
    private VendorEntity vendor;
    @EJB
    private bean.session.RawMaterialEntityFacade facade;
    @EJB
    private bean.session.VendorProductPriceEntityFacade vfacade;
    @EJB
    private bean.session.VendorEntityFacade ejbFacade;
    
    @EJB
    private bean.session.BackorderEntityFacade backOrderFacade;
    
   

    public VendorProductPriceEntityFacade getVfacade() {
        return vfacade;
    }

    public void setVfacade(VendorProductPriceEntityFacade vfacade) {
        this.vfacade = vfacade;
    }

    public RawMaterialEntityFacade facade() {
        return facade;
    }

    public void setFacade(RawMaterialEntityFacade facade) {
        this.facade = facade;
    }

    public VendorEntity getVendor() {
        if (getLoginVendor() != null) {
            return getLoginVendor();
        }
        return null;
    }

    public void setVendor(VendorEntity vendor) {
        this.vendor = vendor;
    }
    private VendorEntity selectedVendor;
//////////////////////////////////////////  
    private RawMaterialQuotationEntity selectedRmq;

    public RawMaterialQuotationEntity getSelectedRmq() {
        return selectedRmq;
    }

    public void setSelectedRmq(RawMaterialQuotationEntity selectedRmq) {
        this.selectedRmq = selectedRmq;
    }
    private List<RawMaterialQuotationEntity> RmqPurchaseList = new ArrayList<RawMaterialQuotationEntity>();

    public List<RawMaterialQuotationEntity> getRmqPurchaseList() {
        return RmqPurchaseList;
    }

    public void setRmqPurchaseList(List<RawMaterialQuotationEntity> RmqPurchaseList) {
        this.RmqPurchaseList = RmqPurchaseList;
    }

    public VendorEntity getSelectedVendor() {
        return selectedVendor;
    }

    public void setSelectedVendor(VendorEntity selectedVendor) {
        this.selectedVendor = selectedVendor;
    }
    private VendorEntity current;

    public VendorEntityFacade getEjbFacade() {
        return ejbFacade;
    }

    public void setEjbFacade(VendorEntityFacade ejbFacade) {
        this.ejbFacade = ejbFacade;
    }

    public RawMaterialPurchaseOrderEditController() {
    }
    @EJB
    private bean.session.RawMaterialQuotationFacade rqFacade;
    @EJB
    private bean.session.RawMaterialPurchaseOrderEntityFacade rpFacade;

    public RawMaterialPurchaseOrderEntityFacade getRpFacade() {
        return rpFacade;
    }

    public void setRpFacade(RawMaterialPurchaseOrderEntityFacade rpFacade) {
        this.rpFacade = rpFacade;
    }

    public RawMaterialQuotationFacade getRqFacade() {
        return rqFacade;
    }

    public void setRqFacade(RawMaterialQuotationFacade rqFacade) {
        this.rqFacade = rqFacade;
    }
    private Collection<RawMaterialQuotationEntity> rmqs;

    public Collection<RawMaterialQuotationEntity> getRmqs() {
        return getRqFacade().getQuotedQuotation();
    }

    public void setRmqs(Collection<RawMaterialQuotationEntity> rmqs) {
    }
    //in the purchase list or not

    public boolean checkPurchaseList(RawMaterialQuotationEntity r1) {
        for (RawMaterialQuotationEntity r : getRmqPurchaseList()) {
            if ((r1.getRawMaterial().getProductName().equalsIgnoreCase(r.getRawMaterial().getProductName()))
                    && (r.getValidity().equals(r1.getValidity()))) {
                System.out.println();
                return true;
            }
        }
        return false;
    }

    public Collection<RawMaterialQuotationEntity> updateRejectedQuotation() {
        Collection<RawMaterialQuotationEntity> result = new ArrayList<RawMaterialQuotationEntity>();

        for (RawMaterialQuotationEntity r : getRmqs()) {
            System.out.println(r.getPrice() + "kkkkk");
            if (checkPurchaseList(r)) {
                result.add(r);
            }
        }
        return result;
    }

    public String createPurchase() {

        for (RawMaterialQuotationEntity rmq : getRmqPurchaseList()) {
            VendorEntity v = rmq.getVendor();
            rmq.setType(RawMaterialQuotationType.accepted);
            getRqFacade().edit(rmq);
            //Collection<RawMaterialQuotationEntity> rmqs =new ArrayList<RawMaterialQuotationEntity>();
            RawMaterialPurchaseOrderEntity rpo = new RawMaterialPurchaseOrderEntity();
            rpo.setRmq(rmq);
            rpo.setAmountLeft(rmq.getQuantity());

            rpo.setStatus(RawMaterialPurchaseOrderStatus.pending);

            getRpFacade().create(rpo);
            v.getRawMaterialPurchases().add(rpo);

            getEjbFacade().edit(v);

        }

        Collection<RawMaterialQuotationEntity> result = updateRejectedQuotation();
        if (result.size() != 0) {
            for (RawMaterialQuotationEntity r : result) {

                r.setType(RawMaterialQuotationType.rejected);
                getRqFacade().edit(r);
            }
        }
        RmqPurchaseList.clear();

        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Purchased Order issued.Rejected Quotation updated ", "Purchased Order issued.Rejected Quotation updated "));
        return "PriceComparison?faces-redirect=true";
    }
    //pending order
    private Collection<RawMaterialPurchaseOrderEntity> rpos;
    private RawMaterialPurchaseOrderEntity currPurchaseOrder;

    public RawMaterialPurchaseOrderEntity getCurrPurchaseOrder() {
        return currPurchaseOrder;
    }

    public void setCurrPurchaseOrder(RawMaterialPurchaseOrderEntity currPurchaseOrder) {
        this.currPurchaseOrder = currPurchaseOrder;
    }

    public RawMaterialPurchaseOrderEntity getSelectedPurchaseOrder() {
        return selectedPurchaseOrder;
    }

    public void setSelectedPurchaseOrder(RawMaterialPurchaseOrderEntity selectedPurchaseOrder) {
        this.selectedPurchaseOrder = selectedPurchaseOrder;
    }
    private RawMaterialPurchaseOrderEntity selectedPurchaseOrder;

    public Collection<RawMaterialPurchaseOrderEntity> getRpos() {
        return getRpFacade().getPendingOrder1();
    }

    public void setRpos(Collection<RawMaterialPurchaseOrderEntity> rpos) {
        this.rpos = rpos;
    }

    public String purchaseOrderSelect(SelectEvent event) {

        currPurchaseOrder = selectedPurchaseOrder;

        quantity = Double.toString(currPurchaseOrder.getQuantity());
        price = Double.toString(currPurchaseOrder.getPrice());
        cost = Double.toString(currPurchaseOrder.getCost());
        figureCost = Double.toString((currPurchaseOrder.getQuantity()) * (currPurchaseOrder.getPrice()));
        bankAccount = currPurchaseOrder.getRmq().getVendor().getBankAccount();
        return "OrderDetail?faces-redirect=true";
    }

    public String purchaseOrderSelect1(SelectEvent event) {

        currPurchaseOrder = selectedPurchaseOrder;


        return "MaintainOrder?faces-redirect=true";
    }
    //all purchase order
    private Collection<RawMaterialPurchaseOrderEntity> rposs;

    public Collection<RawMaterialPurchaseOrderEntity> getRposs() {
        return getRpFacade().getPendingOrder();
    }

    public void setRposs(Collection<RawMaterialPurchaseOrderEntity> rposs) {
        this.rposs = rposs;
    }
    //amount rm shipped
    private double amount;

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }
    //day receive the product 
    private Date validity;

    public Date getValidity() {
        return validity;
    }

    public void setValidity(Date validity) {
        this.validity = validity;
    }

    public String editOrder() {
        // total quantity of this order
        double total = currPurchaseOrder.getRmq().getQuantity();
        Double filled = new Double(0);
        HashMap cur = currPurchaseOrder.getShip();
        Collection c = cur.values();

        for (Object key : cur.keySet()) {
            filled += (Double) cur.get(key);
        }

        //the amount has already been filled for this order 
        double fill = filled.doubleValue();

        //amount is the quantity of this particular shipment
        if (amount + fill < total) {
            cur.put(validity, new Double(amount));
            double left = total - amount - fill;
            currPurchaseOrder.setShipAmount(cur);
            currPurchaseOrder.setStatus(RawMaterialPurchaseOrderStatus.partlyfilled);
            currPurchaseOrder.setAmountLeft(left);
            getRpFacade().edit(currPurchaseOrder);

            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, new FacesMessage("Purchase Order Updated ", "The amount left is " + left + " out of " + total));
        } else if (amount + fill == total) {
            cur.put(validity, new Double(amount));
            currPurchaseOrder.setDateConfirmed(validity);
            currPurchaseOrder.setStatus(RawMaterialPurchaseOrderStatus.fulfilled);
            currPurchaseOrder.setAmountLeft(0);
            currPurchaseOrder.setShipAmount(cur);
            getRpFacade().edit(currPurchaseOrder);
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, new FacesMessage("Purchase Order Updated ", "Order filled entirely"));
        } else {
            FacesContext context = FacesContext.getCurrentInstance();
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "This is absurd.Check it again!!", "U pay for " + total + " and they ship more than that??? "));

        }
        validity = null;
        amount = 0;
        currPurchaseOrder = null;
        return "main?faces-redirect=true";
    }
    //for rating order
    private Collection<RawMaterialPurchaseOrderEntity> fulfilledRposs;

    public Collection<RawMaterialPurchaseOrderEntity> getFulfilledRposs() {
        return getRpFacade().getFulffiledOrder();
    }

    public void setFulfilledRposs(Collection<RawMaterialPurchaseOrderEntity> fulfilledRposs) {
        this.fulfilledRposs = fulfilledRposs;
    }
    private RawMaterialPurchaseOrderEntity currRpo;

    public RawMaterialPurchaseOrderEntity getCurrRpo() {
        return currRpo;
    }

    public void setCurrRpo(RawMaterialPurchaseOrderEntity currRpo) {
        this.currRpo = currRpo;
    }
    private RawMaterialPurchaseOrderEntity selectedRpo;

    public RawMaterialPurchaseOrderEntity getSelectedRpo() {
        return selectedRpo;
    }

    public void setSelectedRpo(RawMaterialPurchaseOrderEntity selectedRpo) {
        this.selectedRpo = selectedRpo;
    }

    public String RPOSelect(SelectEvent event) {
        currRpo = selectedRpo;
        return "RateOrder?faces-redirect=true";

    }

    public void scheduleDelivery() {
        HashMap ship = currPurchaseOrder.getSettleShip();
        HashMap schedule = currPurchaseOrder.getScheduleShip();

        schedule.put(validity, new Double(amount));
        ship.put(validity, new Double(amount));
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Updated", "Scheduled shipment Added in "));


        validity = null;
        amount = 0;


    }

//    public void editDelivery() {
//
//        currPurchaseOrder.setScheduleShip(new HashMap());
//
////        getRpFacade().edit(currPurchaseOrder);
//        FacesContext context = FacesContext.getCurrentInstance();
//        context.addMessage(null, new FacesMessage("Updated", "Scheduled shipment Added in "));
//
//
//        validity = null;
//        amount = 0;
//
//
//    }
    public boolean checkFirstDayOfMonthIsMondayOrSunday(Calendar ca) {
        String[] strDays = new String[]{"Sunday", "Monday", "Tuesday",
            "Wednesday", "Thusday",
            "Friday", "Saturday"};
        String day = strDays[ca.get(Calendar.DAY_OF_WEEK) - 1];
        System.out.println(day + "jjj");
        if (day.equalsIgnoreCase("Monday") || day.equalsIgnoreCase("Sunday")) {
            return true;
        }
        return false;
    }

    public String resetSchedule() {
        HashMap ship = currPurchaseOrder.getSettleShip();
        HashMap schedule = currPurchaseOrder.getScheduleShip();
        schedule.clear();
        ship.clear();
        getRpFacade().edit(currPurchaseOrder);
      
        return "";
    }

    public String doneSchedule() {
        currPurchaseOrder.setUpdated(true);
        getRpFacade().edit(currPurchaseOrder);
        HashMap schedule = currPurchaseOrder.getScheduleShip();

        Set set = schedule.entrySet();

        Iterator i = set.iterator();
        Calendar calendar = Calendar.getInstance();
        while (i.hasNext()) {

            Map.Entry me = (Map.Entry) i.next();
            if (me.getKey() == null) {
                calendar.setTime(new Date());
            } else {
                calendar.setTime((Date) me.getKey());
            }
            Double amt = (Double) me.getValue();
            calendar.add(Calendar.DATE, 7);
            double amount = amt.doubleValue();
            int WeekOfMonth = calendar.get(Calendar.WEEK_OF_MONTH);
            int year = calendar.get(Calendar.YEAR);;
            int month = calendar.get(Calendar.MONTH);
            System.out.println(Month.fromMonthNum(month + 1) + "rrrr");


            RawMaterialPurchaseOrderReportEntity r = new RawMaterialPurchaseOrderReportEntity();
            r.setProduct(currPurchaseOrder.getRmq().getRawMaterial());
            //Eddie ,SunWei ,edit here.What do u want to set for this new RawMaterialPurchaseOrderReportEntity
            r.setQuantity(new Double(amount).longValue());


            //0:what u need to modify.take in mind the schedule .....
            r.setExpectedYearOfReceipt(year);
            r.setExpectedMonthOfReceipt(Month.fromMonthNum(month + 1));

            Calendar cal = Calendar.getInstance();
            cal.set(year, month, 1);
            if(!checkFirstDayOfMonthIsMondayOrSunday(cal)){
               r.setExpectedWeekOfReceipt(WeekOfMonth-1);
               int currentWeek = WeekOfMonth-1;  
              if(currentWeek ==0){ // means it's previous month's week 5
              currentWeek = backOrderFacade.findPreviousMonthLastWeekNum(cal);
              r.setExpectedWeekOfReceipt(currentWeek);
              }
              if(r.getExpectedMonthOfRecepit()!=Month.JANUARY){
                  r.setExpectedMonthOfReceipt(Month.fromMonthNum(month));
              }
              else{
                  r.setExpectedYearOfReceipt(year-1);
                  r.setExpectedMonthOfReceipt(Month.DECEMBER);
              }
             }
            
            RawMaterialPurchaseOrderReportEntity result = getRmpo().findReport(r);
            if (result == null) {
                getRmpo().create(r);
                
            } else {
                result.setQuantity(result.getQuantity() + r.getQuantity());
            }
            
            RawMaterialRequirementWeeklyEntity mrp = backOrderFacade.findMrp(r.getExpectedYearOfReceipt(), r.getExpectedMonthOfRecepit(), r.getExpectedWeekOfReceipt(),r.getProduct());
            RawMaterialRequirementWeeklyEntity orderMrp = backOrderFacade.findOrderWeekMrp(r.getExpectedYearOfReceipt(), r.getExpectedMonthOfRecepit(), r.getExpectedWeekOfReceipt(),r.getProduct());
            System.out.println(r.getExpectedYearOfReceipt()+" "+r.getExpectedMonthOfRecepit()+" "+r.getExpectedWeekOfReceipt()+" "+r.getQuantity());    
            if(mrp!=null){
                    mrp.setScheduledReceipt(r);
                    mrp.setPlannedReceipt(mrp.getPlannedReceipt()-r.getQuantity());
                    
                   
                }
                if(orderMrp!=null){
                    orderMrp.setPlannedOrderQuantity(orderMrp.getPlannedOrderQuantity()-r.getQuantity());
                }
        }
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Scheduled shipment Confirmed", "Scheduled shipment Confirmed for this order"));



        validity = null;
        amount = 0;
        return "main?faces-redirect=true";
    }
//    private HashMap schedule=new HashMap(); ;
//
//    public HashMap getSchedule() {
//        return schedule;
//    }
    @EJB
    private bean.session.RawMaterialPurchaseOrderReportEntityFacade rmpo;

    public RawMaterialPurchaseOrderReportEntityFacade getRmpo() {
        return rmpo;
    }

    public void setRmpo(RawMaterialPurchaseOrderReportEntityFacade rmpo) {
        this.rmpo = rmpo;
    }
//    public void setSchedule(HashMap schedule) {
//        this.schedule = schedule;
//    }
    //schedule ship
    private List scheduleShip;

    public List getScheduleShip() {
        scheduleShip = new ArrayList(currPurchaseOrder.getScheduleShip().entrySet());
        Iterator it = scheduleShip.iterator();

        return scheduleShip;
    }

    public void setScheduleShip(List scheduleShip) {
        this.scheduleShip = scheduleShip;
    }
    //shipment of fulfilled order
    private List entrySet;

    public List getEntrySet() {
        entrySet = new ArrayList(currRpo.getShip().entrySet());
        Iterator it = entrySet.iterator();

        return entrySet;
    }

    public void setEntrySet(List entrySet) {
        this.entrySet = entrySet;
    }

    public void handleRate(RateEvent rateEvent) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Rate Event", "You rated:" + (int) rateEvent.getRating());
        currRpo.setStar((double) rateEvent.getRating());


        getRpFacade().edit(currRpo);


        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public String back() {
        currRpo.setStatus(RawMaterialPurchaseOrderStatus.fulfilled);
        currRpo.setNote(note);
        getRpFacade().edit(currRpo);
        VendorEntity v = currRpo.getRmq().getVendor();

        Collection<RawMaterialPurchaseOrderEntity> rawMaterialPurchases = v.getRawMaterialPurchases();


        double total = 0;
        int count = 0;
        for (RawMaterialPurchaseOrderEntity r : rawMaterialPurchases) {
            System.out.println(r.getStar() + "rrrrrrr");
            total += r.getStar();
            count++;
        }
        v.setStar(Round((double) (total / count), 2));
        System.out.println((double) (total / count) + "ffffffffff");
        getEjbFacade().edit(v);
        note = "";
        return "EditOrder?faces-redirect=true";

    }

    public static double Round(double Rval, int Rpl) {
        double p = (double) Math.pow(10, Rpl);
        Rval = Rval * p;
        double tmp = Math.round(Rval);
        return (double) tmp / p;
    }
    private Collection<RawMaterialPurchaseOrderEntity> finishedRpos;

    public Collection<RawMaterialPurchaseOrderEntity> getFinishedRpos() {
        return getRpFacade().getFulffiledOrder();
    }

    public void setFinishedRpos(Collection<RawMaterialPurchaseOrderEntity> finishedRpos) {
        this.finishedRpos = finishedRpos;
    }
    private String note;

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }
    private String price;
    private String cost;

    public String getCost() {
        return cost;
    }

    public void setCost(String cost) {
        this.cost = cost;
    }

    public String getFigureCost() {
        return figureCost;
    }

    public void setFigureCost(String figureCost) {
        this.figureCost = figureCost;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getQuantity() {
        return quantity;
    }

    public void setQuantity(String quantity) {
        this.quantity = quantity;
    }
    private String quantity;
    private String figureCost;
    private String bankAccount;

    public String getBankAccount() {
        return bankAccount;
    }

    public void setBankAccount(String bankAccount) {
        this.bankAccount = bankAccount;
    }

    public String payment() {
        currPurchaseOrder.setBankAccount(bankAccount);
        currPurchaseOrder.setUpdated(true);
        getRpFacade().edit(currPurchaseOrder);
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Updated", "Payment Info Updated"));
        return "main?faces-redirect=true";
    }

    public String done() {
        currPurchaseOrder.setPrice(Double.parseDouble(price));
        currPurchaseOrder.setFigureCost(Double.parseDouble(figureCost));
        currPurchaseOrder.setCost(Double.parseDouble(cost));
        currPurchaseOrder.setQuantity(Double.parseDouble(quantity));
        currPurchaseOrder.setAmountLeft(Double.parseDouble(quantity));
        currPurchaseOrder.setUpdated(true);
        getRpFacade().edit(currPurchaseOrder);
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("Updated", "Order Information Changed"));
        return "main?faces-redirect=true";
    }

    public String confirm() {

  currPurchaseOrder.setUpdated(true);
        getRpFacade().edit(currPurchaseOrder);
        currPurchaseOrder = null;
        return "EditOrder?faces-redirect=true";
    }
    private AddressEntity address;
    private AddressEntity billAddress;

    public AddressEntity getBillAddress() {
        Collection<AddressEntity> li = selectedRpo.getRmq().getVendor().getContact().getAddresses();
        for (AddressEntity a : li) {
            if (a.getType().equals(AddressType.BillingAddress)) {
                return a;
            }
        }
        return null;
    }

    public void setBillAddress(AddressEntity billAddress) {
        this.billAddress = billAddress;
    }

    public AddressEntity getAddress() {
        Collection<AddressEntity> li = currPurchaseOrder.getRmq().getVendor().getContact().getAddresses();
        for (AddressEntity a : li) {
            if (a.getType().equals(AddressType.HomeAddress)) {
                return a;
            }
        }
        return null;

    }

    public void setAddress(AddressEntity address) {
        this.address = address;
    }
}
